package gsoc.ogsadai.client;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import uk.org.ogsadai.activity.ActivityContractName;
import uk.org.ogsadai.client.toolkit.DataRequestExecutionResource;
import uk.org.ogsadai.client.toolkit.RequestExecutionType;
import uk.org.ogsadai.client.toolkit.RequestResource;
import uk.org.ogsadai.client.toolkit.Resource;
import uk.org.ogsadai.client.toolkit.ResourceProperty;
import uk.org.ogsadai.client.toolkit.ServerProxy;
import uk.org.ogsadai.client.toolkit.document.DocumentWorkflow;
import uk.org.ogsadai.client.toolkit.exception.ClientServerCompatibilityException;
import uk.org.ogsadai.client.toolkit.exception.ClientToolkitException;
import uk.org.ogsadai.client.toolkit.exception.RequestExecutionException;
import uk.org.ogsadai.client.toolkit.exception.ResourceUnknownException;
import uk.org.ogsadai.client.toolkit.exception.ServerCommsException;
import uk.org.ogsadai.client.toolkit.exception.ServerException;
import uk.org.ogsadai.resource.ResourceID;
import uk.org.ogsadai.resource.ResourcePropertyName;
import uk.org.ogsadai.resource.ResourceType;
import uk.org.ogsadai.resource.property.ActivitiesMetaData;
import uk.org.ogsadai.resource.property.ActivityMetaData;

/*
 *
 * @author Nicola Salvo
 */
public class ServerClient {

	public final static String DEFAULT_URL = "http://localhost:8080/wsrf/services/dai/";
	
	private String url = DEFAULT_URL;
	private ServerProxy server;
	
	public ServerClient(String _URL) throws MalformedURLException{
		this.url = _URL;
		server = new ServerProxy();
		server.setDefaultBaseServicesURL(new URL(url));
	}
	
	/**
	 * List all the resources exposed on OGSA-DAI server. In order to return in a single String
	 * the Resource name and the Resource type a structured format is used.
	 * 
	 * TODO write an helper class containing resource name e resource type, in order to avoid returning 
	 * 		a structured string, that needs to be parsed by the caller.
	 * 
	 * @return Every element of the collection is structured as ResourceLocalPart+":"ResourceType
	 * @throws Exception
	 */

	public Collection listResoucesAll() throws Exception {

		
		ResourceID[] resourcesArray = server.listResources(ResourceType.DATA_REQUEST_EXECUTION_RESOURCE);
		Collection resources = new ArrayList();

		for (int i = 0; i < resourcesArray.length; i++) {
			resources.add(resourcesArray[i].getLocalPart() + ":"
					+ ResourceType.DATA_REQUEST_EXECUTION_RESOURCE);
		}

		resourcesArray = server.listResources(ResourceType.DATA_RESOURCE);
		for (int i = 0; i < resourcesArray.length; i++) {
			resources.add(resourcesArray[i].getLocalPart() + ":"
					+ ResourceType.DATA_RESOURCE);
		}

		resourcesArray = server.listResources(ResourceType.SESSION);
		for (int i = 0; i < resourcesArray.length; i++) {
			resources.add(resourcesArray[i].getLocalPart() + ":"
					+ ResourceType.SESSION);
		}

		resourcesArray = server.listResources(ResourceType.REQUEST);
		for (int i = 0; i < resourcesArray.length; i++) {
			resources.add(resourcesArray[i].getLocalPart() + ":"
					+ ResourceType.REQUEST);
		}

		resourcesArray = server.listResources(ResourceType.DATA_SOURCE);
		for (int i = 0; i < resourcesArray.length; i++) {
			resources.add(resourcesArray[i].getLocalPart() + ":"
					+ ResourceType.DATA_SOURCE);
		}

		resourcesArray = server.listResources(ResourceType.DATA_SINK);
		for (int i = 0; i < resourcesArray.length; i++) {
			resources.add(resourcesArray[i].getLocalPart() + ":"
					+ ResourceType.DATA_SINK);
		}

		return resources;
	}
	
	/**
	 * Lists all the activities that are associated with the resource
	 * 
	 * @param ResourceID
	 * @param ResourceType
	 * @return Collection of String containing the ActivityName
	 * @throws Exception
	 */

	public Collection<String> listResourceActivity(String strResourceID,
			String strResourceType) throws Exception {
		List<String> activities = new ArrayList<String>();
	
		ResourceID resourceID = new ResourceID(strResourceID);
		ResourceType resourceType = ResourceType.getResourceType(strResourceType);

		Resource resource = server.getResource(resourceID, resourceType);
		ActivitiesMetaData activitiesMetaData = resource.getActivityDetails();

		ActivityMetaData[] activityMetaData = activitiesMetaData
				.getActivityMetaData();
		for (int i = 0; i < activityMetaData.length; i++) {
			ActivityMetaData activity = activityMetaData[i];
			activities.add(activity.getActivityName().toString());
		}

		return activities;
	}
	

	/**
	 * Lists all the activities that are associated with the default resource DataRequestExecutionResource
	 * 
	 * @return Collection of String containing the ActivityName
	 */
	public Collection<String> listResoucreDefaultActivity() throws ServerCommsException, Exception, ClientServerCompatibilityException, ClientToolkitException, ResourceUnknownException {
		List<String> activities = new ArrayList<String>();
		
		ResourceID drerID = new ResourceID("DataRequestExecutionResource");
		DataRequestExecutionResource mDRER = server.getDataRequestExecutionResource(drerID);
		ActivitiesMetaData activitiesMetaData = mDRER.getActivityDetails();

		ActivityMetaData[] activityMetaData = activitiesMetaData
				.getActivityMetaData();
		for (int i = 0; i < activityMetaData.length; i++) {
			ActivityMetaData activity = activityMetaData[i];
			activities.add(activity.getActivityName().toString());
		}
		return activities;
	}
	
	/**
	 * This method uses the OGSA-DAI Extension pack to obtain from an file a Workflow.
	 * 
	 * TODO Reading the file from the file system is highly inefficient, mainly because the XML is 
	 * 		already loaded with  the workflow diagram. Is easy to add a new method that accept a
	 * 		Document object as parameter. The problem with that is that there is a conflict with
	 * 		the xerces library used by OGSA-DAI and the one that is used by EMF. 
	 *       
	 * @param docPath XML file containing the description of the workflow
	 * @return
	 * @see uk.org.ogsadai.client.toolkit.document.DocumentWorkflow
	 * @see uk.org.ogsadai.client.toolkit.Workflow
	 * @throws Exception
	 */
	public RequestResource executeRequest(String docPath)
			throws Exception {

		String drerIDStr = "DataRequestExecutionResource";
		ResourceID drerID = new ResourceID(drerIDStr);
		RequestExecutionType execType = RequestExecutionType.SYNCHRONOUS;

		DataRequestExecutionResource drer = server
				.getDataRequestExecutionResource(drerID);
		DocumentWorkflow workflow = new DocumentWorkflow(docPath);
		RequestResource request = null;
		try {
			request = drer.execute(workflow, execType);

		} catch (RequestExecutionException e) {
			System.out.println(e.getRequestResource().getRequestStatus());
			throw e;
		}
		return request;
	}

}